package avicit.bdp.dds.api.controller;

import avicit.bdp.common.dto.request.dds.ProcessSchedulerDto;
import avicit.bdp.common.utils.BdpLogUtil;
import avicit.bdp.common.utils.DateUtils;
import avicit.bdp.dds.dispatch.enums.FailureStrategy;
import avicit.bdp.dds.dispatch.enums.Priority;
import avicit.bdp.dds.dispatch.enums.ReleaseState;
import avicit.bdp.dds.dispatch.enums.WarningType;
import avicit.bdp.dds.api.dto.ScheduleParam;
import avicit.bdp.dds.api.service.SchedulerService;
import avicit.bdp.dds.common.utils.ParameterUtils;
import avicit.bdp.dds.dao.entity.ProjectUser;
import avicit.bdp.dds.dao.entity.Schedule;
import avicit.platform6.api.system.ConvertColumnClient;
import avicit.platform6.api.system.impl.SystemConstant;
import avicit.platform6.commons.utils.BusinessUtil;
import avicit.platform6.core.exception.BusinessException;
import avicit.platform6.core.rest.msg.QueryRespBean;
import avicit.platform6.core.rest.msg.ResponseMsg;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author mayj
 * 流程定义定时管理
 */
@RestController
@Api(tags = "流程定义定时管理")
@RequestMapping("/api/bdp/dds/schedule")
public class SchedulerRest {

    private static final Logger logger = LoggerFactory.getLogger(SchedulerRest.class);

    @Autowired
    private SchedulerService schedulerService;
    @Autowired
    private ConvertColumnClient convertColumnClient;

    /**
     * 创建定时任务
     */
    @PostMapping(value = "/create")
    @ApiOperation(value = "创建定时任务")
    public ResponseMsg<Boolean> createSchedule(@RequestBody ProcessSchedulerDto dto) {

        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(schedulerService.insertSchedule(dto));
        return responseMsg;
    }

    /**
     * 修改定时任务
     */
    @PostMapping(value = "/update")
    @ApiOperation(value = "修改定时任务")
    public ResponseMsg<Boolean> updateSchedule(@RequestBody ProcessSchedulerDto dto) {

        if (StringUtils.isBlank(dto.getId())) {
            throw new BusinessException("ID不能为空!");
        }

        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(schedulerService.updateSchedule(dto));
        return responseMsg;
    }


    /**
     * 分页查询调度任务列表
     */
    @ApiOperation(value = "分页查询调度配置列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "processDefinitionId", value = "流程定义id", dataType = "String"),
            @ApiImplicitParam(name = "searchVal", value = "关键词", dataType = "String"),
            @ApiImplicitParam(name = "pageNo", value = "当前页", dataType = "Int"),
            @ApiImplicitParam(name = "pageSize", value = "每页大小", dataType = "Int")
    })
    @GetMapping("/list-paging")
    public ResponseMsg<QueryRespBean<Schedule>> queryScheduleListPaging(@RequestParam String processDefinitionId,
                                                                        @RequestParam(value = "searchVal", required = false) String searchVal,
                                                                        @RequestParam("pageNo") Integer pageNo,
                                                                        @RequestParam("pageSize") Integer pageSize) {

        logger.info("query schedule, process definition id: {}", processDefinitionId);

        searchVal = ParameterUtils.handleEscapes(searchVal);
        QueryRespBean<Schedule> res = schedulerService.querySchedule(processDefinitionId, searchVal, pageNo, pageSize);

        ResponseMsg<QueryRespBean<Schedule>> respBeanResponseMsg = new ResponseMsg<>();
        respBeanResponseMsg.setResponseBody(res);
        return respBeanResponseMsg;
    }

    /**
     * 删除调度配置列表
     */
    @ApiOperation(value = "删除调度配置列表")
    @ApiImplicitParam(name = "scheduleId", value = "调度id", dataType = "String")
    @GetMapping(value = "/delete")
    public ResponseMsg<Boolean> deleteScheduleById(@RequestParam("scheduleId") String scheduleId) {

        if (StringUtils.isBlank(scheduleId)) {
            throw new BusinessException("ID不能为空!");
        }

        logger.info("delete schedule by id, schedule id:{}", scheduleId);

        ResponseMsg<Boolean> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(schedulerService.deleteScheduleById(scheduleId));
        return responseMsg;
    }

    @ApiOperation(value = "获取调度配置")
    @ApiImplicitParam(name = "scheduleId", value = "调度id", dataType = "String")
    @GetMapping(value = "/getSchedule")
    public ResponseMsg<Schedule> getScheduleById(@RequestParam("scheduleId") String scheduleId) {

        if (StringUtils.isBlank(scheduleId)) {
            throw new BusinessException("ID不能为空!");
        }

        logger.info("get schedule by id, schedule id:{}", scheduleId);

        ResponseMsg<Schedule> responseMsg = new ResponseMsg<>();
        Schedule query = new Schedule();
        query.setProcessDefinitionId(scheduleId);
        List<Schedule> list = schedulerService.selectList(query);
        Schedule result = new Schedule();
        if(list != null && !list.isEmpty()){
            result = list.get(0);
        }else{
            Date now = new Date();
            result.setStartTime(now);
            result.setEndTime(DateUtils.getSomeDay(now,365));
            result.setFailureStrategy(FailureStrategy.END.getCode());
            result.setProcessInstancePriority(Priority.MEDIUM.getCode());
            result.setWarningType(WarningType.NONE.getCode());
            result.setWarningUserIds("");
        }
        BdpLogUtil.log4Query(result);
        responseMsg.setResponseBody(result);
        return responseMsg;
    }


    /**
     * 预览调度配置
     *
     * @param scheduleParam schedule param
     * @return
     */
    @PostMapping("/preview")
    @ApiOperation(value = "预览调度配置")
    public ResponseMsg<List<Date>> previewSchedule(@RequestBody ScheduleParam scheduleParam) {
        logger.info("preview schedule: {}", scheduleParam);

        ResponseMsg<List<Date>> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(schedulerService.previewSchedule(scheduleParam));
        return responseMsg;
    }

    /**
     * publish schedule setScheduleState
     *
     * @param id scheduler id
     * @return publish result code
     */
    @ApiOperation(value = "上线调度配置")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "SCHEDULE_ID", dataType = "String"),
            @ApiImplicitParam(name = "projectName", value = "PROJECT_NAME", dataType = "String")
    })
    @GetMapping("/online")
    public ResponseMsg<Map<String, Object>> online(@RequestParam(value = "projectName", defaultValue = "default") String projectName,
                                                   @RequestParam("id") String id) {

        logger.info("schedule setScheduleState, project name: {}, id: {}", projectName, id);

        ResponseMsg<Map<String, Object>> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(schedulerService.setScheduleState(projectName, id, ReleaseState.ONLINE));
        return responseMsg;
    }

    /**
     * offline schedule
     *
     * @param projectName project name
     * @param id          schedule id
     * @return operation result code
     */
    @ApiOperation(value = "下线调度配置")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "定时id", dataType = "String"),
            @ApiImplicitParam(name = "projectName", value = "数据空间名称", dataType = "String")
    })
    @GetMapping("/offline")
    public ResponseMsg<Map<String, Object>> offline(@RequestParam(value = "projectName", defaultValue = "default") String projectName,
                                                    @RequestParam("id") String id) {
        logger.info("schedule offline, project name: {}, process definition id: {}", projectName, id);

        ResponseMsg<Map<String, Object>> responseMsg = new ResponseMsg<>();
        responseMsg.setResponseBody(schedulerService.setScheduleState(projectName, id, ReleaseState.OFFLINE));
        return responseMsg;
    }
    /**
     * 获取项目调度告警通知人列表
     * @param projectId
     * @return
     */
    @ApiOperation(value = "获取项目调度告警通知人列表")
    @ApiImplicitParam(name = "projectId", value = "数据空间id", dataType = "String")
    @GetMapping("/getProjectUserList")
    public ResponseMsg<List<ProjectUser>> getProjectUserList(@RequestParam("projectId") String projectId) {
        logger.info("获取用户列表，数据空间Id{}", projectId);

        ResponseMsg<List<ProjectUser>> responseMsg = new ResponseMsg<>();
        List<ProjectUser> userList = schedulerService.getProjectUserList(projectId);
        valueConvert(userList);
        responseMsg.setResponseBody(userList);
        return responseMsg;
    }

    private void valueConvert(List<ProjectUser> userList) {
        //循环组装请求数据
        Map<String, Set<String>> convertFormData = new HashMap<>();
        for (ProjectUser projectUser : userList) {
            BusinessUtil.createConvertSet(convertFormData, SystemConstant.USER, projectUser.getUserId());
        }
        if (convertFormData.size() > 0) {
            //获取请求结果
            Map<String, Map<String, String>> convertResultData = convertColumnClient.replace(convertFormData);
            //循环设置Alias或Name的值
            for (ProjectUser projectUser : userList) {
                projectUser.setUserName(BusinessUtil.convertFormat(convertResultData, SystemConstant.USER,
                        projectUser.getUserId()));
            }
        }
    }

}
